/**
 * build_project
 * <p>
 * Copyright 2014 cayden.cn, Inc. All rights reserved.
 *
 * @author Administrator
 * @date 2021-09-28 13:13
 */
package com.cayden.base.base.db.weight;

import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;

/**
 *
 * @author cayden
 * 对于数据库权重大概的计算,需要对权重进行大概的测试
 * @date 2021-09-28 13:13
 */
@Setter
@Getter
@Slf4j
public class WeightUtils {
    /**
     * 原子类,对于权重的记录,这里的思想主要是和权重取余,
     * 然后对每个区间进行排序,就知道应该访问那个数据库了
     * 但是这个可能效率很低,需要对接口进行压测,选择随机均匀分布还是强均匀分布
     * 测试增加一亿次之后发现其实效率还行,暂时就这样
     */
    public static AtomicLong currSlaveIndex = new AtomicLong(1L);

    /**
     * 对于slave key的计算
     * @return
     */
    public static Integer getSlaveKey(Map<String,Integer> weights,Boolean hasZeroStart){
        // 计算总算力
        int sumWeight = 0;
        for (int weight : weights.values()){
            sumWeight += weight;
        }

        long increment = currSlaveIndex.getAndIncrement();
        long currSlaveIndex = Math.abs(increment % sumWeight);

        int weightIndexSum = 0;
        for(String key : weights.keySet()){
            Integer weightIndex = weights.get(key);
            weightIndexSum += weightIndex;
            if (weightIndexSum > currSlaveIndex){
                String[] split = key.split("_");
                return chooseSlave(split,hasZeroStart);
            }
            continue;
        }

        return 0;
    }

    public static int chooseSlave(String[] key, Boolean slaveIndexHasZeoStart) {
        if (slaveIndexHasZeoStart){
            return Integer.valueOf(key[1]);
        }else {
            return Integer.valueOf(key[1]) - 1;
        }
    }
}
